package com.godyhm.example.userendport;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.Dialog;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.godyhm.example.userendport.Protocol.Protocol;
import com.godyhm.example.userendport.Protocol.ProtocolPacket;

public class UserEndPortActivity extends Activity {
	private final String TAG = getClass().getSimpleName();
	private Button mBtnUp;
	private Button mBtnDown;
	private Button mBtnLeft;
	private Button mBtnCenter;
	private Button mBtnRight;
	private Button mBtnRecord;
	private TextView mTxtRecordTime;
	private TextView mTxtRecordPath;
	private TextView mTextLog;
	private EditText mEditTextAddr;
	private Button mBtnSetAddress;
	private String logInfo = "";
	private final static short CODE_KEY_UP = 1;
	private final static short CODE_KEY_DOWN = 3;
	private final static short CODE_KEY_LEFT = 2;
	private final static short CODE_KEY_CENTER = 0;
	private final static short CODE_KEY_RIGHT = 4;
	private final static int CODE_KEY_ACTION_DOWN = 0;
	private final static int CODE_KEY_ACTION_UP = 1;
	private short mSessionId = 0;
	private short mMessageId = 0;
	private Socket mSocket;
	boolean isTcpServerConnected = false;
	private DataOutputStream mSocketDos;
	private DataInputStream mSocketDis;
	private List<ProtocolPacket> mListMsgToMobile = new ArrayList<ProtocolPacket>();
	private Object mMsgToMobileLock = new Object();
	private static final String KEYBOARD_EVENT_DESCRIPTION = "keyboard_event";
	private static final String VOICE_EVENT_DESCRIPTION="voice_event";
	private static final String KEY_HEAD_DESCRIPTION = "datatype";
	private final int MSG_RECORD_FINISHED=3;
	private final int MSG_SHOW_LOG=4;
	private Dialog dialog;
//	private AudioRecorder mr;
	private OfflineEngineRecorder mRecorder;
    private Thread mRecoderThread;
	private Thread recordThread;
	private short mLineAudioFameSendMsgId=-1;
	private static int MAX_TIME = 15; // 最长录制时间，单位秒，0为无时间限制
	private static int MIX_TIME = 1; // 最短录制时间，单位秒，0为无时间限制，建议设为1

	private static int RECORD_NO = 0; // 不在录音
	private static int RECORD_ING = 1; // 正在录音
	private static int RECODE_ED = 2; // 完成录音

	private static int RECODE_STATE = 0; // 录音的状态

	private static float recodeTime = 0.0f; // 录音的时间
	private static double voiceValue = 0.0; // 麦克风获取的音量值

	private ImageView dialog_img;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViews();
		initViews();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
	}

	private void findViews() {
		mBtnUp = (Button) findViewById(R.id.btn_up);
		mBtnDown = (Button) findViewById(R.id.btn_down);
		mBtnLeft = (Button) findViewById(R.id.btn_left);
		mBtnCenter = (Button) findViewById(R.id.btn_center);
		mBtnRight = (Button) findViewById(R.id.btn_right);
		mBtnRecord = (Button) findViewById(R.id.btn_record);
		mTxtRecordTime = (TextView) findViewById(R.id.txt_record_time);
		mTxtRecordPath = (TextView) findViewById(R.id.txt_record_path);
		mTextLog = (TextView) findViewById(R.id.txt_log_msg);
		mEditTextAddr = (EditText) findViewById(R.id.server_address);
		mBtnSetAddress = (Button) findViewById(R.id.btn_set_address);
		
	}

	private void initViews() {
	    mBtnSetAddress.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                Constants.SERVER_ADDR = mEditTextAddr.getText().toString().trim();
                Log.d(getClass().getSimpleName(),"Get new Server Address "+ Constants.SERVER_ADDR);
                if (!isTcpServerConnected) {
                    new TcpClientThread().start();
                }
                startSendMsgThread();
            }
        });
		mBtnUp.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					SendKeyBoardMessage(CODE_KEY_UP, CODE_KEY_ACTION_DOWN,
							System.currentTimeMillis());
					break;
				case MotionEvent.ACTION_UP:
					SendKeyBoardMessage(CODE_KEY_UP, CODE_KEY_ACTION_UP,
							System.currentTimeMillis());
					break;
				}
				return false;
			}
		});
		mBtnDown.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					SendKeyBoardMessage(CODE_KEY_DOWN, CODE_KEY_ACTION_DOWN,
							System.currentTimeMillis());
					break;
				case MotionEvent.ACTION_UP:
					SendKeyBoardMessage(CODE_KEY_DOWN, CODE_KEY_ACTION_UP,
							System.currentTimeMillis());
					break;
				}
				return false;
			}
		});
		mBtnLeft.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					SendKeyBoardMessage(CODE_KEY_LEFT, CODE_KEY_ACTION_DOWN,
							System.currentTimeMillis());
					break;
				case MotionEvent.ACTION_UP:
					SendKeyBoardMessage(CODE_KEY_LEFT, CODE_KEY_ACTION_UP,
							System.currentTimeMillis());
					break;
				}
				return false;
			}
		});
		mBtnCenter.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					SendKeyBoardMessage(CODE_KEY_CENTER, CODE_KEY_ACTION_DOWN,
							System.currentTimeMillis());
					break;
				case MotionEvent.ACTION_UP:
					SendKeyBoardMessage(CODE_KEY_CENTER, CODE_KEY_ACTION_UP,
							System.currentTimeMillis());
					break;
				}
				return false;
			}
		});
		mBtnRight.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					SendKeyBoardMessage(CODE_KEY_RIGHT, CODE_KEY_ACTION_DOWN,
							System.currentTimeMillis());
					break;
				case MotionEvent.ACTION_UP:
					SendKeyBoardMessage(CODE_KEY_RIGHT, CODE_KEY_ACTION_UP,
							System.currentTimeMillis());
					break;
				}
				return false;
			}
		});

		mBtnRecord.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					if (RECODE_STATE != RECORD_ING) {
//						scanOldFile();
//						mr = new AudioRecorder("voice");
//						RECODE_STATE = RECORD_ING;
//						showVoiceDialog();
//						try {
//							mr.start();
//						} catch (IOException e) {
//							// TODO Auto-generated catch block
//							e.printStackTrace();
//						}
//						mythread();
			            mRecorder = new OfflineEngineRecorder();
			            mRecorder.setRecordingStatus(true);
			            mRecoderThread = new Thread(mRecorder);
			            mRecoderThread.start();
					}
					break;
				case MotionEvent.ACTION_UP:
//					if (RECODE_STATE == RECORD_ING) {
//						RECODE_STATE = RECODE_ED;
//						if (dialog.isShowing()) {
//							dialog.dismiss();
//						}
//						try {
//							mr.stop();
//							voiceValue = 0.0;
//						} catch (IOException e) {
//							e.printStackTrace();
//						}
//						if (recodeTime < MIX_TIME) {
//							showWarnToast();
//							mBtnRecord.setText("按住开始录音");
//							RECODE_STATE = RECORD_NO;
//						} else {
//							mHandler.sendEmptyMessage(MSG_RECORD_FINISHED);
//							mBtnRecord.setText("录音完成!点击重新录音");
//							mTxtRecordTime.setText("录音时间：" + ((int) recodeTime));
//							mTxtRecordPath.setText("文件路径：" + getAmrPath());
//						}
//					}
					if(mRecorder !=null ){
						mRecorder.setRecordingStatus(false);
					}
					mHandler.sendEmptyMessage(MSG_RECORD_FINISHED);
					break;
				}
				return false;
			}
		});
	}

	void scanOldFile() {
		File file = new File(Environment.getExternalStorageDirectory(),
				"voicetest/voice.amr");
		if (file.exists()) {
			file.delete();
		}
	}

	// 录音时显示Dialog
	void showVoiceDialog() {
		dialog = new Dialog(this, R.style.DialogStyle);
		dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
		dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		dialog.setContentView(R.layout.my_dialog);
		dialog_img = (ImageView) dialog.findViewById(R.id.dialog_img);
		dialog.show();
	}

	// 录音时间太短时Toast显示
	void showWarnToast() {
		Toast toast = new Toast(this);
		LinearLayout linearLayout = new LinearLayout(this);
		linearLayout.setOrientation(LinearLayout.VERTICAL);
		linearLayout.setPadding(20, 20, 20, 20);

		// 定义一个ImageView
		ImageView imageView = new ImageView(this);
		imageView.setImageResource(R.drawable.voice_to_short); // 图标

		TextView mTv = new TextView(this);
		mTv.setText("时间太短   录音失败");
		mTv.setTextSize(14);
		mTv.setTextColor(Color.WHITE);// 字体颜色
		// mTv.setPadding(0, 10, 0, 0);

		// 将ImageView和ToastView合并到Layout中
		linearLayout.addView(imageView);
		linearLayout.addView(mTv);
		linearLayout.setGravity(Gravity.CENTER);// 内容居中
		linearLayout.setBackgroundResource(R.drawable.record_bg);// 设置自定义toast的背景

		toast.setView(linearLayout);
		toast.setGravity(Gravity.CENTER, 0, 0);// 起点位置为中间 100为向下移100dp
		toast.show();
	}

	// 获取文件手机路径
	private String getAmrPath() {
		File file = new File(Environment.getExternalStorageDirectory(),"voicetest/voice.amr");
		return file.getAbsolutePath();
	}

	// 录音计时线程
	void mythread() {
		recordThread = new Thread(ImgThread);
		recordThread.start();
	}

	// 录音Dialog图片随声音大小切换
	void setDialogImage() {
		if (voiceValue < 200.0) {
			dialog_img.setImageResource(R.drawable.record_animate_01);
		} else if (voiceValue > 200.0 && voiceValue < 400) {
			dialog_img.setImageResource(R.drawable.record_animate_02);
		} else if (voiceValue > 400.0 && voiceValue < 800) {
			dialog_img.setImageResource(R.drawable.record_animate_03);
		} else if (voiceValue > 800.0 && voiceValue < 1600) {
			dialog_img.setImageResource(R.drawable.record_animate_04);
		} else if (voiceValue > 1600.0 && voiceValue < 3200) {
			dialog_img.setImageResource(R.drawable.record_animate_05);
		} else if (voiceValue > 3200.0 && voiceValue < 5000) {
			dialog_img.setImageResource(R.drawable.record_animate_06);
		} else if (voiceValue > 5000.0 && voiceValue < 7000) {
			dialog_img.setImageResource(R.drawable.record_animate_07);
		} else if (voiceValue > 7000.0 && voiceValue < 10000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_08);
		} else if (voiceValue > 10000.0 && voiceValue < 14000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_09);
		} else if (voiceValue > 14000.0 && voiceValue < 17000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_10);
		} else if (voiceValue > 17000.0 && voiceValue < 20000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_11);
		} else if (voiceValue > 20000.0 && voiceValue < 24000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_12);
		} else if (voiceValue > 24000.0 && voiceValue < 28000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_13);
		} else if (voiceValue > 28000.0) {
			dialog_img.setImageResource(R.drawable.record_animate_14);
		}
	}

	// 录音线程
	private Runnable ImgThread = new Runnable() {

		@Override
		public void run() {
			recodeTime = 0.0f;
			while (RECODE_STATE == RECORD_ING) {
				if (recodeTime >= MAX_TIME && MAX_TIME != 0) {
					mHandler.sendEmptyMessage(0);
				} else {
					try {
						Thread.sleep(200);
						recodeTime += 0.2;
						if (RECODE_STATE == RECORD_ING) {
//							voiceValue = mr.getAmplitude();
							if(mRecorder!=null){
								voiceValue=mRecorder.getCurrentDBLevelMeter();
							}
							mHandler.sendEmptyMessage(1);
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	};

	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {
			case 0:
				// 录音超过15秒自动停止
				if (RECODE_STATE == RECORD_ING) {
					RECODE_STATE = RECODE_ED;
					if (dialog.isShowing()) {
						dialog.dismiss();
					}
//					try {
//						mr.stop();
						if(mRecorder !=null ){
							mRecorder.setRecordingStatus(false);
						}
						voiceValue = 0.0;
//					} catch (IOException e) {
//						e.printStackTrace();
//					}

					if (recodeTime < 1.0) {
						showWarnToast();
						mBtnRecord.setText("按住开始录音");
						RECODE_STATE = RECORD_NO;
					} else {
						mHandler.sendEmptyMessage(MSG_RECORD_FINISHED);
						mBtnRecord.setText("录音完成!点击重新录音");
						mTxtRecordTime.setText("录音时间：" + ((int) recodeTime));
						mTxtRecordPath.setText("文件路径：" + getAmrPath());
					}
				}
				break;
			case 1:
				setDialogImage();
				break;
			case MSG_RECORD_FINISHED:
				sendVoice();
				break;
			case MSG_SHOW_LOG:
				setLog(""+msg.obj);
				break;
			default:
				break;
			}
		}
	};
	
	private void sendMessage(int what, Object obj) {
		if(obj!=null){
			if(obj instanceof String){
				Log.i(TAG, (String)obj);
			}else{
				Log.d(TAG, new String((byte[]) obj));
			}
		}
		Message msg = new Message();
		msg.what = what;
		msg.obj = obj;
		mHandler.sendMessage(msg);
	}
	private void setLog(String logStr) {
		//bad performance
//		if (TextUtils.isEmpty(logInfo)) {
//			mTextLog.setText(logStr);
//			logInfo = logStr;
//		} else {
//			if (!TextUtils.isEmpty(logStr)) {
//				logInfo += "\n";
//				logInfo += logStr;
//			}
//			mTextLog.setText(logInfo);
//		}
		
		mTextLog.setText(logStr);
	}
	
	private void sendVoice(){
		StringBuilder headDescription=new StringBuilder();
		headDescription.append(KEY_HEAD_DESCRIPTION);
		headDescription.append(":");
		headDescription.append(VOICE_EVENT_DESCRIPTION);
	    int desLength=headDescription.length();
		int headLength=1+1+desLength;
		sendMessage(MSG_SHOW_LOG,"send voice start frame headLength="+headLength+", realMessageLength="+0);
	    byte data[]=new byte[headLength];
	    int dataoffset=0;
		data[dataoffset++]=(byte) headLength;
		data[dataoffset++]=0x01;
		System.arraycopy(headDescription.toString().getBytes(), 0, data, dataoffset, desLength);
		sendLineAudioSessionFrameStart(data);
	}
	
	
	/**
	 * consecutive frame
	 * */
	private void sendLineAudioSessionFrameStart(byte descriptiondata[]) {
		sendMessage(MSG_SHOW_LOG,"send play audio fisrt frame to device!");
		mLineAudioFameSendMsgId=generateMessageId();
		ProtocolPacket pp = new ProtocolPacket(Protocol.PROTOCOL_VERSION,
				false, Protocol.FRAME_TYPE_BINARY,
				Protocol.FRAME_TYPE_BINARY_AUDIO,
				Protocol.FRAME_TYPE_CONNECTION_TYPE_TRANSMISSION_START,
				mLineAudioFameSendMsgId,// message id
				generateSessionId(), (short) 0, descriptiondata==null?0:descriptiondata.length, descriptiondata);
		sendMessage(MSG_SHOW_LOG,"sendLineAudioSessionFrameStart!");
		pushFrameToList(pp);
		new SendFileThread().start();
	}
	
	public static String getMd5ByFile(File file) {
		String value = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);
			MappedByteBuffer byteBuffer = in.getChannel().map(
					FileChannel.MapMode.READ_ONLY, 0, file.length());
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(byteBuffer);
			BigInteger bi = new BigInteger(1, md5.digest());
			value = bi.toString(16);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return value;
	}

	class SendFileThread extends Thread {
		public void run() {
			FileInputStream fis=null;
			try {
				int sendBufSize = 1024;
//				FileInputStream fis=new FileInputStream(new File(getAmrPath()));
				File f=new File(Environment.getExternalStorageDirectory()+ "/dump-baidu.pcm");
				if(!f.exists()){
					sendMessage(MSG_SHOW_LOG, "SendFileThread file not exist return!");
					return;
				}
				String sendfmd5=getMd5ByFile(f);
				Log.e(TAG, "dump-baidu.pcm md5="+sendfmd5);
				fis=new FileInputStream(f);
				sendMessage(MSG_SHOW_LOG, "SendFileThread file available:" + fis.available());
				byte[] sendBuf = new byte[sendBufSize];
				int readLength = 0;
				int curPos = 0;
				// 写入数据即播放
				while ((readLength = fis.read(sendBuf)) != -1) {
					curPos += readLength;
//					sendMessage(MSG_SHOW_LOG, "SendFileThread read pos=" + curPos);
					byte[] tmpBuf = new byte[readLength];
					System.arraycopy(sendBuf, 0, tmpBuf, 0, readLength);
					sendLineAudioSessionFrameData(tmpBuf);
					
				}
				sendLineAudioSessionFrameEnd(null);
				sendMessage(MSG_SHOW_LOG, "SendFileThread end curPos="+curPos);
				f.delete();
			}catch(Exception e){
				e.printStackTrace();
				sendMessage(MSG_SHOW_LOG,"SendFileThread Error:" + e.getMessage());
			}catch (Throwable t) {
				t.printStackTrace();
				sendMessage(MSG_SHOW_LOG,"SendFileThread Error:" + t.getMessage());
			}finally {
				if(fis!=null){
					try {
						fis.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	};
	
	private void sendLineAudioSessionFrameData(byte data[]) {
//		sendMessage(MSG_SHOW_LOG,"send audio frame data to device! "+data.length);
		ProtocolPacket pp = new ProtocolPacket(Protocol.PROTOCOL_VERSION,
				false, Protocol.FRAME_TYPE_BINARY,
				Protocol.FRAME_TYPE_BINARY_AUDIO,
				Protocol.FRAME_TYPE_CONNECTION_TYPE_DATA_TRANSFER,
				mLineAudioFameSendMsgId,// message id
				generateSessionId(), (short) 0, data.length, data);
		pushFrameToList(pp);
	}
	
	private void sendLineAudioSessionFrameEnd(byte data[]) {
		sendMessage(MSG_SHOW_LOG,"send audio last frame to device!");
		ProtocolPacket pp = new ProtocolPacket(Protocol.PROTOCOL_VERSION,
				false, Protocol.FRAME_TYPE_BINARY,
				Protocol.FRAME_TYPE_BINARY_AUDIO,
				Protocol.FRAME_TYPE_CONNECTION_TYPE_TRANSMISSION_END,
				mLineAudioFameSendMsgId,// message id
				generateSessionId(), (short) 0, data==null?0:data.length, data);
		sendMessage(MSG_SHOW_LOG,"sendLineAudioSessionFrameEnd");
		pushFrameToList(pp);
	}
	
	private short generateSessionId() {
		if (mSessionId == 0) {
			mSessionId = (short) (Math.random() * 1000);
		}
		return mSessionId;
	}

	private short generateMessageId() {
		short msgId = 0;
		if (msgId == 0) {
			msgId = (short) (Math.random() * 1000);
		}
		return msgId;
	}

	private Protocol.RESULT_CODE SendKeyBoardMessage(short keycode, int value,
			long time) {
		sendMessage(MSG_SHOW_LOG, "SendKeyBoardMessage keycode="+keycode+", value="+value+", time="+time);
		short type = 1;
		int realMessageLength = 16;// should 24
		StringBuilder headDescription = new StringBuilder();
		headDescription.append(KEY_HEAD_DESCRIPTION);
		headDescription.append(":");
		headDescription.append(KEYBOARD_EVENT_DESCRIPTION);
		int desLength = headDescription.length();
		int headLength = 1 + 1 + desLength;
		int dataLength = headLength + realMessageLength;
		byte data[] = new byte[dataLength];
		int dataoffset = 0;
		data[dataoffset++] = (byte) headLength;
		data[dataoffset++] = 0x01;
		System.arraycopy(headDescription.toString().getBytes(), 0, data,
				dataoffset, desLength);
		dataoffset += desLength;
		data[dataoffset++] = (byte) (type >> 8);
		data[dataoffset++] = (byte) (type);
		data[dataoffset++] = (byte) (keycode >> 8);
		data[dataoffset++] = (byte) (keycode);
		data[dataoffset++] = (byte) (value >> 24);
		data[dataoffset++] = (byte) (value >> 16);
		data[dataoffset++] = (byte) (value >> 8);
		data[dataoffset++] = (byte) (value);
		data[dataoffset++] = (byte) (time >> 56);
		data[dataoffset++] = (byte) (time >> 48);
		data[dataoffset++] = (byte) (time >> 40);
		data[dataoffset++] = (byte) (time >> 32);
		data[dataoffset++] = (byte) (time >> 24);
		data[dataoffset++] = (byte) (time >> 16);
		data[dataoffset++] = (byte) (time >> 8);
		data[dataoffset++] = (byte) (time);
		ProtocolPacket packet = new ProtocolPacket(Protocol.PROTOCOL_VERSION,
				false, Protocol.FRAME_TYPE_COMMON,
				Protocol.FRAME_TYPE_COMMON_SINGLE,
				Protocol.FRAME_TYPE_CONNECTION_TYPE_DATA_TRANSFER,
				generateMessageId(), generateSessionId(), (short) 0,
				dataLength, data);
		sendMessage(MSG_SHOW_LOG, "SendKeyBoardMessage frameData="+Bytes2HexString(packet.getPacket()));
		pushFrameToList(packet);
		return Protocol.RESULT_CODE.RESULT_OK;
	}

	private void pushFrameToList(ProtocolPacket p) {
		synchronized (mMsgToMobileLock) {
			mListMsgToMobile.add(p);
//			sendMessage(MSG_SHOW_LOG,"mListMsgToMobile size="+mListMsgToMobile.size());
		}
	}
	private final static int IN_BUF_SIZE = 8192;
	class TcpClientThread extends Thread {
		public void run() {
			try {
				mSocket = new Socket(Constants.SERVER_ADDR, Constants.TCP_PORT_NUMBER);
				sendMessage(MSG_SHOW_LOG,"TcpClientThread server is connected!");
				isTcpServerConnected = true;
				mSocketDis=new DataInputStream(mSocket.getInputStream());
				mSocketDos = new DataOutputStream(mSocket.getOutputStream());
				int readLength = 0;
				byte[] readBuf = new byte[IN_BUF_SIZE];
				int totalLength = 0;
				while (readLength != -1) {
					readLength = mSocketDis.read(readBuf);
					totalLength += readLength;
//					sendMessage(MSG_SHOW_LOG, "TcpClientThread Read " + totalLength+ " byte From Server, current: "+ readLength);
					byte[] tmpBuffer = new byte[readLength];
					System.arraycopy(readBuf, 0, tmpBuffer, 0, readLength);
//					synchronized (mRawMsgFromDevice) {
//						mListRawMsgFromDevice.add(new RawMessage(tmpBuffer,readLength,MSG_FROM_TCP_SINGLE));
//					}
				}
				sendMessage(MSG_SHOW_LOG, "TcpClientThread end!");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				closeTcpSocket();
				sendMessage(MSG_SHOW_LOG, "TcpClientThread exception," + e.getMessage());
			}
		}
	}

	private void closeTcpSocket() {
		if (mSocketDos != null) {
			try {
				mSocketDos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			mSocketDos = null;
		}

		if (mSocket != null) {
			try {
				mSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			mSocket = null;
		}
		sendMessage(MSG_SHOW_LOG, "disconnect from tcp server");
		isTcpServerConnected = false;
	}
	
	private boolean isSendMessageThreadRun=false;
	int totalSend=0;
	private void startSendMsgThread(){
		if(isSendMessageThreadRun){
			return;
		}
		new Thread(){
			public void run(){
				sendMessage(MSG_SHOW_LOG, "startSendMsgThread running");
				isSendMessageThreadRun=true;
				while(isSendMessageThreadRun){
					synchronized (mMsgToMobileLock) {
						if (mListMsgToMobile != null
								&& mListMsgToMobile.size() > 0) {
							ProtocolPacket p = mListMsgToMobile.get(0);
							if (p == null) {
								// Log.e(TAG, "Error get null packet!");
								continue;
							}
							if (mSocketDos != null) {
								try {
									mSocketDos.write(p.getPacket());
									totalSend+=p.getPacketSize();
//									sendMessage(MSG_SHOW_LOG,"Total Send="+totalSend+", current send="+p.getPacketSize());
									mListMsgToMobile.remove(0);
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
									sendMessage(MSG_SHOW_LOG,"startSendMsgThread IOException e=" + e.getMessage());
									closeTcpSocket();
									break;
								} catch (NullPointerException e) {
									e.printStackTrace();
									closeTcpSocket();
									sendMessage(MSG_SHOW_LOG,"startSendMsgThread NullPointerException e="+ e.getMessage());
									break;
								}
							}
						}
					}
				}
				isSendMessageThreadRun=false;
				sendMessage(MSG_SHOW_LOG, "startSendMsgThread end!");
			}
		}.start();
	}
	public String Bytes2HexString(byte[] b) {
		String ret = "";
		for (int i = 0; i < b.length; i++) {
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			if (i < b.length - 1) {
				ret += "0x" + hex.toUpperCase() + ",";
			} else {
				ret += "0x" + hex.toUpperCase();
			}
		}
		return ret;
	}
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		closeTcpSocket();
	}

}
